package com.xjrsoft.module.form.service.impl;

import cn.hutool.core.util.PageUtil;
import cn.hutool.db.*;
import cn.hutool.db.dialect.Dialect;
import cn.hutool.db.dialect.DialectFactory;
import cn.hutool.db.sql.*;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.baomidou.mybatisplus.extension.toolkit.JdbcUtils;
import com.xjrsoft.common.dbmodel.DbExecutor;
import com.xjrsoft.common.dbmodel.SqlParam;
import com.xjrsoft.common.dbmodel.TableColumnInfo;
import com.xjrsoft.common.dbmodel.XjrDb;
import com.xjrsoft.common.dbmodel.entity.TableField;
import com.xjrsoft.common.dbmodel.entity.TableInfo;
import com.xjrsoft.common.dbmodel.utils.DataSourceUtil;
import com.xjrsoft.common.dbmodel.utils.SqlUtil;
import com.xjrsoft.common.dbmodel.utils.TableInfoUtil;
import com.xjrsoft.common.handler.DataAuthHandler;
import com.xjrsoft.common.interceptor.DataAuthInnerInterceptor;
import com.xjrsoft.common.page.ConventPage;
import com.xjrsoft.common.page.PageOutput;
import com.xjrsoft.common.runner.XjrSqlConnRunner;
import com.xjrsoft.common.utils.DataTransUtil;
import com.xjrsoft.core.tool.utils.*;
import com.xjrsoft.module.base.entity.XjrBaseModule;
import com.xjrsoft.module.base.entity.XjrBaseTempfield;
import com.xjrsoft.module.base.service.IXjrBaseCodeRuleService;
import com.xjrsoft.module.base.service.IXjrBaseDatabaseLinkService;
import com.xjrsoft.module.base.service.IXjrBaseModuleService;
import com.xjrsoft.module.base.service.IXjrBaseTempfieldService;
import com.xjrsoft.module.base.utils.OrganizationCacheUtil;
import com.xjrsoft.module.form.constant.FormConstants;
import com.xjrsoft.module.form.dto.FormSchemeDto;
import com.xjrsoft.module.form.dto.FormSchemePageListDto;
import com.xjrsoft.module.form.dto.TableFieldDto;
import com.xjrsoft.module.form.dto.TableInfoDto;
import com.xjrsoft.module.form.entity.XjrFormRelation;
import com.xjrsoft.module.form.entity.XjrFormScheme;
import com.xjrsoft.module.form.entity.XjrFormSchemeInfo;
import com.xjrsoft.module.form.mapper.XjrFormSchemeInfoMapper;
import com.xjrsoft.module.form.service.IXjrFormRelationService;
import com.xjrsoft.module.form.service.IXjrFormSchemeInfoService;
import com.xjrsoft.module.form.service.IXjrFormSchemeService;
import com.xjrsoft.module.form.util.FormDataUtil;
import com.xjrsoft.module.form.util.FormSqlUtil;
import com.xjrsoft.module.form.vo.FormSchemeInfoVo;
import com.xjrsoft.module.form.vo.SystemFormVo;
import com.xjrsoft.module.workflow.entity.XjrNwfSchemeinfo;
import com.xjrsoft.module.workflow.service.IXjrNwfSchemeInfoService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.collections.map.CaseInsensitiveMap;
import org.apache.commons.lang3.StringUtils;
import org.flowable.engine.HistoryService;
import org.flowable.engine.history.HistoricProcessInstance;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.activation.DataHandler;
import javax.sql.DataSource;
import java.math.BigDecimal;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * <p>
 * 自定义表单信息表 服务实现类
 * </p>
 *
 * @author jobob
 * @since 2020-11-11
 */
@Slf4j
@Service
public class XjrFormSchemeInfoServiceImpl extends ServiceImpl<XjrFormSchemeInfoMapper, XjrFormSchemeInfo> implements IXjrFormSchemeInfoService {


    @Autowired
    private IXjrFormSchemeService schemeService;

    @Autowired
    @Lazy
    private IXjrFormRelationService formRelationService;

    @Autowired
    private IXjrBaseDatabaseLinkService databaseLinkService;

    @Autowired
    private DbExecutor dbExecutor;


    @Autowired
    private IXjrBaseCodeRuleService codeRuleService;

    @Autowired
    private HistoryService historyService;


    @Autowired
    private IXjrBaseTempfieldService xjrBaseTempfieldService;

    @Autowired
    private  DataAuthInnerInterceptor dataAuthInnerInterceptor;

    @Autowired
    private IXjrBaseDatabaseLinkService xjrBaseDatabaseLinkService;

    @Autowired
    private IXjrBaseModuleService moduleService;

    @Autowired
    private IXjrNwfSchemeInfoService nwfSchemeInfoService;


    @Override
    @Transactional
    public boolean addFormScheme(XjrFormScheme scheme, XjrFormSchemeInfo schemeInfo) {
        String schemeInfoId = StringUtil.randomUUID();
        schemeInfo.setId(schemeInfoId);
        scheme.setId(schemeInfo.getSchemeId());
        scheme.setSchemeInfoId(schemeInfoId);
        try {
            this.save(schemeInfo);
            schemeService.save(scheme);
        } catch (Exception e) {
            throw new RuntimeException("保存失败！");
        }
        OrganizationCacheUtil.addCache(OrganizationCacheUtil.FORM_SCHEME_LIST_CACHE_KEY, scheme);
        OrganizationCacheUtil.addCache(OrganizationCacheUtil.FORM_SCHEME_INFO_LIST_CACHE_KEY, schemeInfo);
        return true;
    }

    @Override
    public FormSchemeDto setDefauleValue(FormSchemeDto formSchemeDto) {
        String scheme = formSchemeDto.getSchemeDto().getScheme();
        List<TableInfoDto> tableInfoDtoList = formSchemeDto.getTableInfoDtoList();
        if (StringUtil.isNotBlank(scheme)) {
            JSONObject schemeObject = JSONObject.parseObject(scheme);
            JSONObject data = schemeObject.getJSONObject("data");
            JSONArray fieldsArray = data.getJSONArray("fields");
            for (int i = 0; i < fieldsArray.size(); i++) {
                JSONObject jsonObject = fieldsArray.getJSONObject(i);
                JSONObject config = jsonObject.getJSONObject("__config__");
                String type = jsonObject.getString("__type__");
                String avueType = config.getString("avueType");
                String bindTableField = config.getString("bindTableField");
                String bindTable = config.getString("bindTable");
                if (StringUtil.equalsIgnoreCase(avueType, "textarea") || StringUtil.equalsIgnoreCase(avueType, "ueditor") || StringUtil.equalsIgnoreCase(avueType, "autoCode") || StringUtil.equalsIgnoreCase(avueType, "upload")) {
                    //多行文本、编辑器、编码、上传、意见簿
                    for (TableInfoDto tableInfoDto : tableInfoDtoList) {
                        if (StringUtil.equalsIgnoreCase(tableInfoDto.getName(), bindTable)) {
                            List<TableFieldDto> fields = tableInfoDto.getFields();
                            if (CollectionUtil.isNotEmpty(fields)) {
                                for (TableFieldDto field : fields) {
                                    if (StringUtil.equalsIgnoreCase(field.getName(), bindTableField)) {
                                        config.put("fieldLength", 2000);
                                        field.setLength(2000);
                                        jsonObject.put("__config__", config);
                                        break;
                                    }
                                }
                            }
                        }
                        break;
                    }
                } else if (StringUtil.equalsIgnoreCase(type, "user")) {
                    //人员组件
                    for (TableInfoDto tableInfoDto : tableInfoDtoList) {
                        if (StringUtil.equalsIgnoreCase(tableInfoDto.getName(), bindTable)) {
                            List<TableFieldDto> fields = tableInfoDto.getFields();
                            if (CollectionUtil.isNotEmpty(fields)) {
                                for (TableFieldDto field : fields) {
                                    if (StringUtil.equalsIgnoreCase(field.getName(), bindTableField)) {
                                        config.put("fieldLength", 4000);
                                        field.setLength(4000);
                                        jsonObject.put("__config__", config);
                                        break;
                                    }
                                }
                            }
                        }
                    }
                } else if (StringUtil.equalsIgnoreCase(type, "department")) {
                    //部门组件
                    for (TableInfoDto tableInfoDto : tableInfoDtoList) {
                        if (StringUtil.equalsIgnoreCase(tableInfoDto.getName(), bindTable)) {
                            List<TableFieldDto> fields = tableInfoDto.getFields();
                            if (CollectionUtil.isNotEmpty(fields)) {
                                for (TableFieldDto field : fields) {
                                    if (StringUtil.equalsIgnoreCase(field.getName(), bindTableField)) {
                                        config.put("fieldLength", 500);
                                        field.setLength(500);
                                        jsonObject.put("__config__", config);
                                        break;
                                    }
                                }
                            }
                        }
                    }
                } else {
                    //其他组件
                    for (TableInfoDto tableInfoDto : tableInfoDtoList) {
                        if (StringUtil.equalsIgnoreCase(tableInfoDto.getName(), bindTable)) {
                            List<TableFieldDto> fields = tableInfoDto.getFields();
                            if (CollectionUtil.isNotEmpty(fields)) {
                                for (TableFieldDto field : fields) {
                                    if (StringUtil.equalsIgnoreCase(field.getName(), bindTableField)) {
                                        config.put("fieldLength", 200);
                                        field.setLength(200);
                                        jsonObject.put("__config__", config);
                                        break;
                                    }
                                }
                            }
                        }
                    }
                }
            }
            data.put("fields", fieldsArray);
            schemeObject.put("data", data);
            formSchemeDto.getSchemeDto().setScheme(JSONObject.toJSONString(schemeObject));
        }
        return formSchemeDto;
    }

    @Override
    public PageOutput<FormSchemeInfoVo> getPageList(FormSchemePageListDto pageListDto) {
        String keyword = pageListDto.getKeyword();
        String orderField = pageListDto.getOrderfield();
        if (StringUtil.isEmpty(orderField) || StringUtil.equalsIgnoreCase(orderField, "F_Description")) {
            orderField = "F_CreateDate";
        }
        pageListDto.setOrderfield("si." + orderField);

        IPage<XjrFormSchemeInfo> page = ConventPage.getPage(pageListDto);
        if (!StringUtil.isEmpty(keyword)) {
            keyword = StringPool.PERCENT + keyword + StringPool.PERCENT;
        }
        List<FormSchemeInfoVo> userVoList = this.baseMapper.getPageList(pageListDto.getCategory(), keyword, page);
        return ConventPage.getPageOutput(page.getTotal(), userVoList);
    }

    @Override
    @Transactional
    public boolean updateFormScheme(String schemeInfoId, XjrFormScheme scheme, XjrFormSchemeInfo schemeInfo) {
        schemeInfo.setId(schemeInfoId);
        scheme.setSchemeInfoId(schemeInfoId);
        String schemeId = StringUtil.randomUUID();
        schemeInfo.setSchemeId(schemeId);
        scheme.setId(schemeId);
        try {
            this.updateById(schemeInfo);
            schemeService.saveOrUpdate(scheme);
        } catch (Exception e) {
            throw new RuntimeException("修改失败！");
        }
        OrganizationCacheUtil.updateCache(OrganizationCacheUtil.FORM_SCHEME_INFO_LIST_CACHE_KEY, schemeInfo);
        OrganizationCacheUtil.addCache(OrganizationCacheUtil.FORM_SCHEME_LIST_CACHE_KEY, scheme);
        return true;
    }

    @Override
    public Map<String, Object> getCustomFormData(String formId, String recordId) {
        JSONObject schemeJson = getSchemeJsonByFormId(formId);
        Map<String, Object> resultMap = new HashMap<>();
        if (schemeJson != null) {
            String dbLinkId = schemeJson.getString(FormConstants.DB_LINK_ID);
            JSONArray dbTables = schemeJson.getJSONArray(FormConstants.DB_TABLE);
            JSONObject data = schemeJson.getJSONObject(FormConstants.DATA);
            JSONArray fields = data.getJSONArray(FormConstants.FIELDS);
            Map<String, List<Map<String, Object>>> tableFieldMap = new HashMap<>(dbTables.size());
            Map<String, String> tableOrderMap = new HashMap<>();
            for (Object fieldObj : fields) {
                JSONObject fieldJson = (JSONObject) fieldObj;
                JSONObject config = fieldJson.getJSONObject(FormConstants.CONFIG);
                String componentName = MapUtils.getString(config, "componentName");
                if (StringUtil.equalsIgnoreCase(componentName, "avue-tabs")) {
                    JSONObject tabsMap = config.getJSONObject("childrenObj");
                    for (Object tabObj : tabsMap.values()) {
                        JSONArray tabComponents = (JSONArray) tabObj;
                        for (Object tabComponentObj : tabComponents) {
                            JSONObject tabComponent = (JSONObject) tabComponentObj;
                            buildSelectedFields(tableFieldMap, tabComponent, tableOrderMap);
                        }
                    }
                } else {
                    buildSelectedFields(tableFieldMap, fieldJson, tableOrderMap);
                }
            }
            // 查询数据
            resultMap = new HashMap<>(dbTables.size());
            for (Object tableObj : dbTables) {
                JSONObject dbTable = (JSONObject) tableObj;
                Map<String, Object> conditionMap = new HashMap<>(1);
                boolean isMainTable = StringUtil.isBlank(dbTable.getString(FormConstants.DB_TABLE_RELATION_NAME));
                if (isMainTable) {
                    conditionMap.put(dbTable.getString(FormConstants.DB_TABLE_PK), recordId);
                } else {
                    conditionMap.put(dbTable.getString(FormConstants.DB_TABLE_FIELD), recordId);
                }
                String tableName = dbTable.getString(FormConstants.DB_TABLE_NAME);
                List<Map<String, Object>> columnList = tableFieldMap.get(tableName);
                List<String> columnNameList = columnList.stream().map(field -> MapUtils.getString(field, "fieldName")).collect(Collectors.toList());
                // 添加主键返回
                columnNameList.add(dbTable.getString(FormConstants.DB_TABLE_PK));
                SqlParam sqlParam = FormSqlUtil.buildSimpleSelectFormSqlParam(tableName, columnNameList, conditionMap, tableOrderMap.get(tableName));
                try {
                    List<Entity> resultList = dbExecutor.executeQuery(dbLinkId, sqlParam.getSql(), sqlParam.getPara());
                    for (Map<String, Object> column : columnList) {
                        String fieldName = MapUtils.getString(column, "fieldName");
                        String lazyType = MapUtils.getString(column, "lazyType");
                        for (Map<String, Object> record : resultList) {
                            Object value = record.get(fieldName);
                            if (StringUtil.isEmpty(value)) {
                                break;
                            }
                            //时间日期格式处理
                            if (StringUtil.equalsIgnoreCase(MapUtils.getString(column, "type"), "datetime")) {
                                String dateFormat = null;
                                if (value instanceof LocalDateTime) {
                                    dateFormat = ((LocalDateTime) value).format(DateTimeFormatter.ofPattern(MapUtils.getString(column, "format")));
                                } else if (value instanceof Timestamp) {
                                    dateFormat = ((Timestamp) value).toLocalDateTime().format(DateTimeFormatter.ofPattern(MapUtils.getString(column, "format")));;
                                }
                                record.put(fieldName, dateFormat);
                            }
                            // 懒加载数据处理
                            if (StringUtils.isNotEmpty(lazyType)) {
                                String showName = StringPool.EMPTY;
                                if (StringUtil.equalsIgnoreCase(lazyType, "company")) {
                                    showName = DataTransUtil.getCompanyNameById(String.valueOf(value));
                                } else if (StringUtil.equalsIgnoreCase(lazyType, "department")) {
                                    showName = DataTransUtil.getDepartmentNameById(String.valueOf(value));
                                }
                                record.put(fieldName + "_Name", showName);
                            }
                        }
                    }
                    resultMap.put(tableName, isMainTable ? (CollectionUtil.isNotEmpty(resultList) ? resultList.get(0) : null) : resultList);
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
        return resultMap;
    }

    private void buildSelectedFields(Map<String, List<Map<String, Object>>> tableFieldMap, JSONObject fieldConfig, Map<String, String> tableOrderMap) {
        JSONObject config = fieldConfig.getJSONObject(FormConstants.CONFIG);
        Object childrenObj = config.get(FormConstants.CHILDREN);
        // 表格
        if (childrenObj != null) {
            String bindTable = config.getString(FormConstants.BIND_TABLE);
            List<Map<String, Object>> tableFields = tableFieldMap.get(bindTable);
            if (CollectionUtil.isEmpty(tableFields)) {
                tableFields = new ArrayList<>();
                tableFieldMap.put(bindTable, tableFields);
            }
            JSONArray childrenFields = (JSONArray) childrenObj;
            Boolean useDefaultSort = MapUtils.getBoolean(config, "useDefaultSort", false);
            Integer orderFieldId = MapUtils.getInteger(config, "sortField");
            for (Object childrenFieldObj : childrenFields) {
                JSONObject childrenField = (JSONObject) childrenFieldObj;
                JSONObject childrenConfig = childrenField.getJSONObject(FormConstants.CONFIG);
                String subFieldName = childrenConfig.getString(FormConstants.BIND_TABLE_FIELD);
                Map<String, Object> field = new HashMap<>(4);
                tableFields.add(field);
                field.put("fieldName", subFieldName);
                String fieldType = childrenConfig.getString(FormConstants.FORM_COMPONENT_TYPE);
                field.put("type", fieldType);
                if (StringUtil.equalsIgnoreCase(fieldType, "datetime")) {
                    field.put("format", childrenField.getString("format"));
                }
                // 排序字段
                if (!useDefaultSort && (orderFieldId == MapUtils.getInteger(childrenConfig, "formId"))) {
                    tableOrderMap.put(bindTable, subFieldName);
                }
                // 懒加载字段
                buildLazyType(childrenField, field);
            }
        } else {
            String bindTable = config.getString(FormConstants.BIND_TABLE);
            List<Map<String, Object>> tableFields = tableFieldMap.get(bindTable);
            if (CollectionUtil.isEmpty(tableFields)) {
                tableFields = new ArrayList<>();
                tableFieldMap.put(bindTable, tableFields);
            }
            Map<String, Object> field = new HashMap<>(4);
            field.put("fieldName", config.getString(FormConstants.BIND_TABLE_FIELD));
            String fieldType = config.getString(FormConstants.FORM_COMPONENT_TYPE);
            field.put("type", fieldType);
            if (StringUtil.equalsIgnoreCase(fieldType, "datetime")) {
                field.put("format", fieldConfig.getString("format"));
            }
            // 懒加载字段
            buildLazyType(fieldConfig, field);
            tableFields.add(field);
        }
    }

    private void buildLazyType(JSONObject fieldConfig, Map<String, Object> field) {
        String componentType = fieldConfig.getString(FormConstants.FIELD_TYPE);
        String infoType = fieldConfig.getString(FormConstants.FIELD_TYPE_OF_INFO_TYPE);
        if (StringUtils.equalsIgnoreCase(componentType, "department") || StringUtils.equalsIgnoreCase(componentType, "company")
                || (StringUtils.equalsIgnoreCase(componentType, "info") && (StringUtils.equalsIgnoreCase(infoType, "company") || StringUtils.equalsIgnoreCase(infoType, "department")))) {
            field.put("lazyType", StringUtils.equalsIgnoreCase(componentType, "info") ? infoType : componentType);
        }
    }

    @Override
    public String addCustomFormData(String formId,String fId,Map<String, Object> data) throws Exception {
        XjrFormScheme scheme = getSchemeByFormId(formId);
        JSONObject schemeJson = JSONObject.parseObject(scheme.getScheme());
        // 0-自定义开发模板，1-自定义表结构模板，2-快速开发简易模板(旧版：1.正式2.草稿)
        Integer type = scheme.getType();
        String dbLinkId = schemeJson.getString(FormConstants.DB_LINK_ID);
        JSONArray dbTables = schemeJson.getJSONArray(FormConstants.DB_TABLE);
        Entity mainRecord = null;
        List<List<Entity>> subRecordList = new ArrayList<>();
        String mainId =StringUtil.isNotBlank(fId)?fId: IdWorker.get32UUID();
        JSONObject dataSettingJson = schemeJson.getJSONObject(FormConstants.DATA);
        JSONArray fields = dataSettingJson.getJSONArray(FormConstants.FIELDS);
        // 特殊数据处理
        for (Object fieldObj : fields) {
            JSONObject field = (JSONObject) fieldObj;
            this.dealWithSpecialData(data, field, true);
        }

        // 保存数据准备
        for (Object dbTableObj : dbTables) {
            JSONObject dbTable = (JSONObject) dbTableObj;
            boolean isMainTable = StringUtil.isBlank(dbTable.getString(FormConstants.DB_TABLE_RELATION_NAME));
            String tableName = dbTable.getString(FormConstants.DB_TABLE_NAME);
            if (isMainTable) {
                // 主表
                Map<String, Object> mainData = (Map<String, Object>) data.get(tableName);
                mainRecord = Entity.create(tableName);
                mainRecord.putAll(mainData);
                // 添加主键值
                if(mainRecord.containsKey(dbTable.getString(FormConstants.DB_TABLE_PK))) {
                    mainRecord.remove(dbTable.getString(FormConstants.DB_TABLE_PK));
                }
                mainRecord.put(StringUtils.lowerCase(dbTable.getString(FormConstants.DB_TABLE_PK)), mainId);
                // 添加公共字段填充值
                if (type == 1 || type == 2) {
                    TableInfoUtil.setAddCommonFieldValue(mainRecord);
                }
            } else {
                // 子表
                List<Map<String, Object>> subDataList = (List<Map<String, Object>>) data.get(tableName);
                if (CollectionUtil.isEmpty(subDataList)) {
                    continue;
                }
                List<Entity> savedSubDataList = new ArrayList<>(subDataList.size());
                for (Map<String, Object> subData : subDataList) {
                    Entity record = Entity.create(tableName);
                    record.putAll(subData);
                    // 添加主键值
                    record.put(StringUtils.lowerCase(dbTable.getString(FormConstants.DB_TABLE_PK)), IdWorker.get32UUID());
                    record.put(StringUtils.lowerCase(dbTable.getString(FormConstants.DB_TABLE_FIELD)), mainId);
                    // 添加公共字段填充值
                    if (type == 1 || type == 2) {
                        TableInfoUtil.setAddCommonFieldValue(record);
                    }
                    savedSubDataList.add(record);
                }
                subRecordList.add(savedSubDataList);
            }

        }

        Session session = Session.create(DataSourceUtil.getDataSource(dbLinkId));
        try {
            session.beginTransaction();
            // 保存主表数据
            session.insert(mainRecord);
            // 保存子表数据
            for (List<Entity> subRecords : subRecordList) {
                session.insert(subRecords);
            }
            session.commit();
        } catch (SQLException e) {
            log.error("执行新增sql失败！", e);
            session.quietRollback();
            throw e;
        }
        return mainId;
    }




    private void dealWithSpecialData(Map<String, Object> data, JSONObject field, boolean isNew) {
        JSONObject config = field.getJSONObject(FormConstants.CONFIG);
        String componentName = MapUtils.getString(config, "componentName");
        if (StringUtil.equalsIgnoreCase(componentName, "table")) {
            // 表格
            JSONArray tabFiledList = config.getJSONArray(FormConstants.CHILDREN);
            for (Object tabFieldObj : tabFiledList) {
                JSONObject tabField = (JSONObject) tabFieldObj;
                dealWithSpecialData(data, tabField, isNew);
            }
        } else if (StringUtil.equalsIgnoreCase(componentName, "avue-tabs")) {
            // 选项卡
            JSONObject tabsMap = config.getJSONObject("childrenObj");
            for (Object tabObj : tabsMap.values()) {
                JSONArray tabComponents = (JSONArray) tabObj;
                for (Object tabComponentObj : tabComponents) {
                    JSONObject tabComponent = (JSONObject) tabComponentObj;
                    dealWithSpecialData(data, tabComponent, isNew);
                }
            }
        }
        Object dataOjb = data.get(config.getString(FormConstants.BIND_TABLE));
        if (dataOjb == null) {
            return;
        }
        List<Map<String, Object>> dataList = null;
        if (dataOjb instanceof Map) {
            dataList = new ArrayList<>(1);
            dataList.add((Map<String, Object>) dataOjb);
        } else {
            dataList = (List<Map<String, Object>>) dataOjb;
        }
        String fieldName = config.getString(FormConstants.BIND_TABLE_FIELD);
        String avueType = config.getString(FormConstants.FORM_COMPONENT_TYPE);
        if(StringUtil.isNotBlank(fieldName)) {
            for (Map<String, Object> record : dataList) {
                Object value = record.get(fieldName);
                if (StringUtil.isEmpty(value)) {
                    record.put(fieldName, null);
                    continue;
                }
                if (isNew && StringUtil.equalsIgnoreCase(avueType, FormConstants.COMPONENT_TYPE_OF_CODE_RULE)) {
                    // 自动编码使用
                    codeRuleService.useEncode(config.getString("autoCodeRule"));
                } else if (StringUtil.equalsIgnoreCase(avueType, "datetime")) {
                    // 时间字段转换
                    record.put(fieldName, DateUtil.parse(String.valueOf(value), MapUtils.getString(field, "format", DateUtil.PATTERN_DATETIME)));
                } else if ((StringUtil.equalsIgnoreCase(avueType, "number") || StringUtil.equalsIgnoreCase(avueType, "switch")
                        || StringUtil.equalsIgnoreCase(avueType, "rate") || StringUtil.equalsIgnoreCase(avueType, "slider")
                        || (StringUtil.equalsIgnoreCase(config.getString("tag"), "el-input") && StringUtil.equalsIgnoreCase(avueType, "input"))) && StringUtil.isNumeric(String.valueOf(value))) {
                    // 数字转换
                    record.put(fieldName, new BigDecimal(String.valueOf(value)));
                }
            }
        }
    }

    @Override
    public boolean updateCustomFormData(String formId, String recordId, Map<String, Object> data) {
        XjrFormScheme scheme = getSchemeByFormId(formId);
        JSONObject schemeJson = JSONObject.parseObject(scheme.getScheme());
        // 0-自定义开发模板，1-自定义表结构模板，2-快速开发简易模板(旧版：1.正式2.草稿)
        Integer type = scheme.getType();
        String dbLinkId = schemeJson.getString(FormConstants.DB_LINK_ID);
        JSONArray dbTables = schemeJson.getJSONArray(FormConstants.DB_TABLE);
        JSONObject dataSettingJson = schemeJson.getJSONObject(FormConstants.DATA);
        JSONArray fields = dataSettingJson.getJSONArray(FormConstants.FIELDS);
        // 特殊数据处理
        for (Object fieldObj : fields) {
            JSONObject field = (JSONObject) fieldObj;
            this.dealWithSpecialData(data, field, false);
        }
        List<SqlParam> sqlParamList = new ArrayList<>();
        for (Object dbTableObj : dbTables) {
            JSONObject dbTable = (JSONObject) dbTableObj;
            boolean isMainTable = StringUtil.isBlank(dbTable.getString(FormConstants.DB_TABLE_RELATION_NAME));
            String tableName = dbTable.getString(FormConstants.DB_TABLE_NAME);
            String pk = dbTable.getString(FormConstants.DB_TABLE_PK);
            if (isMainTable) {
                // 主表
                Map<String, Object> mainData = (Map<String, Object>) data.get(tableName);// 添加公共字段填充值
                if (type == 1 || type == 2) {
                    TableInfoUtil.setUpdateCommonFieldValue(mainData);
                }
                SqlParam sqlParam = FormSqlUtil.buildSimpleUpdateSqlParam(tableName, pk, recordId, mainData);
                sqlParamList.add(sqlParam);
            } else {
                // 子表
                // 先删除数据
//                SqlParam deleteSqlParam = FormSqlUtil.buildSimpleDeleteSqlParam(tableName, dbTable.getString(FormConstants.DB_TABLE_FIELD), recordId);
                SqlParam deleteSqlParam = new SqlParam();
                sqlParamList.add(deleteSqlParam);
                List<Map<String, Object>> subDataList = (List<Map<String, Object>>) data.get(tableName);
                String relationField = dbTable.getString(FormConstants.DB_TABLE_FIELD);
                List<String> existIdList = new ArrayList<>();
                for (Map<String, Object> subData : subDataList) {
                    // 添加主键值
                    String id = MapUtils.getString(subData, pk);
                    SqlParam sqlParam = null;
                    if (StringUtils.isEmpty(id)) {
                        subData.put(pk, IdWorker.get32UUID());
                        subData.put(relationField, recordId);// 添加公共字段填充值
                        sqlParam = FormSqlUtil.buildSimpleInsertSqlParam(tableName, subData);
                        if (type == 1 || type == 2) {
                            TableInfoUtil.setAddCommonFieldValue(subData);
                        }
                    } else {
                        sqlParam = FormSqlUtil.buildSimpleUpdateSqlParam(tableName, pk, id, subData);
                        if (type == 1 || type == 2) {
                            TableInfoUtil.setUpdateCommonFieldValue(subData);
                        }
                        existIdList.add(id);
                    }
                    sqlParamList.add(sqlParam);
                }
                // 删除数据sql
                String deleteSql = StringPool.EMPTY;
                if (CollectionUtil.isNotEmpty(existIdList)) {
                    if(existIdList.size() > 1) {
                        deleteSql = FormSqlUtil.buildDeleteSubDataSql(tableName, relationField, recordId, pk, "not in", existIdList.size());
                    } else {
                        deleteSql = FormSqlUtil.buildDeleteSubDataSql(tableName, relationField, recordId, pk, "!=", 1);
                    }
                    deleteSqlParam.addParaList(new ArrayList<>(existIdList));
                    deleteSqlParam.setSql(deleteSql);
                }
            }

        }
        try {
            dbExecutor.batchExecute(dbLinkId, sqlParamList, false);

        } catch (SQLException e) {
            log.error("修改表单数据失败！");
            return false;
        }
        return true;
    }

    @Override
    public boolean deleteCustomFormData(String formId, String recordIds) {
        JSONObject schemeJson = getSchemeJsonByFormId(formId);
        String dbLinkId = schemeJson.getString(FormConstants.DB_LINK_ID);
        JSONArray dbTables = schemeJson.getJSONArray(FormConstants.DB_TABLE);

        List<SqlParam> sqlParamList = new ArrayList<>();
        for (Object dbTableObj : dbTables) {
            JSONObject dbTable = (JSONObject) dbTableObj;
            String tableName = dbTable.getString(FormConstants.DB_TABLE_NAME);
            boolean isMainTable = StringUtil.isBlank(dbTable.getString(FormConstants.DB_TABLE_RELATION_NAME));
            SqlParam sqlParam;
            String[] recordIdArray = StringUtils.split(recordIds, StringPool.COMMA);
            if (isMainTable) {
                sqlParam = FormSqlUtil.buildSimpleDeleteSqlParam(tableName, dbTable.getString(FormConstants.DB_TABLE_PK), recordIdArray);
            } else {
                sqlParam = FormSqlUtil.buildSimpleDeleteSqlParam(tableName, dbTable.getString(FormConstants.DB_TABLE_FIELD), recordIdArray);
            }
            sqlParamList.add(sqlParam);
        }
        try {
            dbExecutor.batchExecute(dbLinkId, sqlParamList, false);
        } catch (SQLException e) {
            return false;
        }
        return true;
    }

    @Override
    public JSONObject getSchemeJsonByFormId(String formId) {
        XjrFormScheme scheme = this.getSchemeByFormId(formId);
        if (scheme != null) {
            return JSONObject.parseObject(scheme.getScheme());
        }
        return null;
    }

    @Override
    public XjrFormScheme getSchemeByFormId(String formId) {
        XjrFormSchemeInfo schemeInfo = this.getById(formId);
        if (schemeInfo != null) {
            return schemeService.getById(schemeInfo.getSchemeId());
        }
        return null;
    }

    @Override
    public Object getCustomListData(String formId, JSONObject settingJson, Map<String, Object> params) throws Exception {
        XjrFormScheme scheme = getSchemeByFormId(formId);
        JSONObject schemeJson = JSONObject.parseObject(scheme.getScheme());
        if (schemeJson == null) {
            throw new Exception("表单已删除");
        }
        Integer flowStatus = null;
        //是否绑定流程
        XjrFormSchemeInfo xjrFormSchemeInfo = this.getById(formId);
        JSONArray dbTables = schemeJson.getJSONArray(FormConstants.DB_TABLE);
        JSONObject columnData = settingJson.getJSONObject(FormConstants.COLUMN_DATA);
        JSONArray fields = columnData.getJSONArray(FormConstants.FIELDS);
        JSONObject form = columnData.getJSONObject(FormConstants.FORM);
        List<String> columnNameList = new ArrayList<>();
        String mainTableName = StringPool.EMPTY;
        String mainPk = StringPool.EMPTY;
        for (Object dbTableObj : dbTables) {
            JSONObject dbTable = (JSONObject) dbTableObj;
            if (StringUtil.isBlank(dbTable.getString(FormConstants.DB_TABLE_RELATION_NAME))) {
                mainTableName = dbTable.getString(FormConstants.DB_TABLE_NAME);
                mainPk = dbTable.getString(FormConstants.DB_TABLE_PK);
                columnNameList.add(mainPk);
                break;
            }
        }
        for (Object fieldObj : fields) {
            JSONObject field = (JSONObject) fieldObj;
            String columnName = field.getString(FormConstants.BIND_COLUMN);
            if (!StringUtil.isEmpty(columnName)) {
                columnNameList.add(columnName);
            }
        }
        JSONObject data = schemeJson.getJSONObject(FormConstants.DATA);
        JSONArray formFields = data.getJSONArray(FormConstants.FIELDS);
        Entity where = Entity.create(mainTableName).setFieldNames(columnNameList);
        // 构建查询条件
        JSONArray queryData = settingJson.getJSONArray(FormConstants.LIST_QUERY_DATA);
        if (CollectionUtil.isNotEmpty(queryData)) {
            for (Object formFieldObj : formFields) {
                JSONObject formField = (JSONObject) formFieldObj;
                JSONObject config = formField.getJSONObject(FormConstants.CONFIG);
                String componentType = config.getString(FormConstants.FORM_COMPONENT_TYPE);
                String componentName = MapUtils.getString(config, FormConstants.FORM_COMPONENT_NAME);
                if (StringUtil.equalsIgnoreCase(componentName, "avue-tabs")) {
                    JSONObject tabsJson = config.getJSONObject("childrenObj");
                    for (Object tabObj : tabsJson.values()) {
                        JSONArray tabComponents = (JSONArray) tabObj;
                        for (Object tabComponentObj : tabComponents) {
                            JSONObject tabComponent = (JSONObject) tabComponentObj;
                            buildQueryExpressions(params, where, queryData, tabComponent, tabComponent.getString(FormConstants.FORM_COMPONENT_TYPE));
                        }
                    }
                } else {
                    buildQueryExpressions(params, where, queryData, formField, componentType);
                }
            }
        }
        String dbLinkId = schemeJson.getString(FormConstants.DB_LINK_ID);
        DataSource dataSource = DataSourceUtil.getDataSource(dbLinkId);
        List<Map<String, Object>> recordList = new ArrayList<>();
        boolean isPage = StringUtil.equals(form.getString(FormConstants.IS_PAGE), "1");
        int total = 0;
        try {
            int limit = isPage ? MapUtils.getInteger(params, FormConstants.PARAM_KEY_PAGE_LIMIT, 1) : -1;
            int size = isPage ? MapUtils.getInteger(params, FormConstants.PARAM_KEY_PAGE_SIZE, 20) : 5000;
            String orderField = MapUtils.getString(params, FormConstants.QUERY_ORDER_FIELD);
            String order = MapUtils.getString(params, FormConstants.QUERY_ORDER);
            // 设置分页起始页号
            PageUtil.setOneAsFirstPageNo();
            Page page = new Page(limit, size);
            if (!StringUtil.isEmpty(orderField)) {
                page.setOrder(new Order(orderField, StringUtil.isEmpty(order) ? Direction.ASC : Direction.fromString(order)));
            }
            PageResult<Entity> pageResult = null;

            // 0-自定义开发模板，1-自定义表结构模板，2-快速开发简易模板(旧版：1.正式2.草稿)
            Integer type = scheme.getType();
            if (type == 1 || type == 2) {
                /** 权限过滤 */
//                DataAuthHandler dataAuthHandler = dataAuthInnerInterceptor.getDataAuthHandler();
//                where.addFieldNames(dataAuthHandler.getDataAuthColumn());
                where.addFieldNames(new DataAuthHandler().getDataAuthColumn());
                Query query = Query.of(where).setFields(where.getFieldNames());
                Dialect dialect = DialectFactory.getDialect(dataSource);
                Wrapper wrapper = dialect.getWrapper();
                // 去掉字段符号，用于权限字段对比
                wrapper.setPreWrapQuote(null);
                wrapper.setSufWrapQuote(null);
                SqlBuilder find = SqlBuilder.create(wrapper).query(query);
                String sql = dataAuthInnerInterceptor.parserMulti(find.toString(), (Object) null);
                SqlBuilder resultSql = SqlBuilder.of(sql).addParams(find.getParamValueArray());
                /** 权限过滤 */
                XjrDb use = XjrDb.use(dataSource);
                use.setRunner(new XjrSqlConnRunner(dialect));
                pageResult = use.page(resultSql, page);
            } else {
                pageResult = Db.use(dataSource).page(where, page);
            }
            for (Entity entity : pageResult) {
                CaseInsensitiveMap caseInsensitiveMap = new CaseInsensitiveMap(entity);
                Map<String, Object> map = new HashMap<>(entity.size());
                for (String columnName : columnNameList) {
                    Object value = caseInsensitiveMap.get(columnName);
                    //数据的主键
                    if (StringUtil.equals(columnName, mainPk)) {
                        map.put(FormConstants.DEFAULT_ID_FIELD_NAME, value);
                        if (xjrFormSchemeInfo != null) {
                            String nwfSchemeinfoId = "";
                            String deploymentId="";
                            nwfSchemeinfoId = xjrFormSchemeInfo.getNwfSchemeinfoId();
                            XjrNwfSchemeinfo xjrNwfSchemeinfo = nwfSchemeInfoService.getById(nwfSchemeinfoId);
                            if(xjrNwfSchemeinfo!=null){
                                deploymentId = xjrNwfSchemeinfo.getDeploymentId();
                            }
                            //获取流程id
                            HistoricProcessInstance historicProcessInstance = null;
                            List<HistoricProcessInstance> historicProcessInstanceList = historyService.createHistoricProcessInstanceQuery().variableValueEquals(formId + StringPool.UNDERSCORE + value).notDeleted().list();
                            for (HistoricProcessInstance processInstance : historicProcessInstanceList) {
                                XjrBaseTempfield xjrBaseTempfield = xjrBaseTempfieldService.getByIdAndType(processInstance.getId(), "18");
                                if (xjrBaseTempfield == null) {
                                    historicProcessInstance = processInstance;
                                    break;
                                }
                            }
                            if (historicProcessInstance == null) {
                                //未发起流程或未完成加入到回收站中可重新发起
                                if (xjrFormSchemeInfo.getNwfSchemeinfoId() == null) {
                                    //未绑定表单
                                    flowStatus = 0;
                                } else {
                                    flowStatus = 1;
                                }
                            } else {
                                //是否被结束
                                QueryWrapper<XjrBaseTempfield> queryWrapper = new QueryWrapper<>();
                                queryWrapper.lambda().eq(XjrBaseTempfield::getFkey, historicProcessInstance.getId()).eq(XjrBaseTempfield::getType, "33").like(XjrBaseTempfield::getFvalue,"流程被结束");
                                XjrBaseTempfield xjrBaseTempfield = xjrBaseTempfieldService.getOne(queryWrapper);
                                if (historicProcessInstance.getEndTime() != null||xjrBaseTempfield!=null) {
                                    //已完成
                                    flowStatus = 3;
                                } else {
                                    //审批中
                                    flowStatus = 2;
                                }
                            }
                            map.put("flowStatus", flowStatus);
                            map.put("nwfSchemeinfoId", nwfSchemeinfoId);
                            map.put("formId", formId);
                            map.put("deploymentId", deploymentId);
                        }
                    } else {
                        map.put(columnName, value);
                    }
                }
                recordList.add(map);
            }
            total = pageResult.getTotal();
        } catch (SQLException e) {
            log.error("查询失败！", e);
            throw new RuntimeException("查询失败: " + e.getMessage());
        }
        // 数据源，数据字典等显示数据转换
        FormDataUtil.transFormListData(formFields, recordList);
        if (isPage) {
            return ConventPage.getPageOutput(Long.valueOf(total), recordList);
        }
        return recordList;
    }

    private void buildQueryExpressions(Map<String, Object> params, Entity where, JSONArray queryData, JSONObject formField, String componentType) {
        JSONObject config = formField.getJSONObject(FormConstants.CONFIG);
        for (Object queryFieldObj : queryData) {
            JSONObject queryField = (JSONObject) queryFieldObj;
            String fieldName = queryField.getString(FormConstants.QUERY_FIELD_NAME);
            if (StringUtil.equals(config.getString(FormConstants.BIND_TABLE_FIELD), fieldName)) {
                String searchType = MapUtils.getString(queryField, "type");
                if (StringUtil.equalsIgnoreCase(searchType, "datetime")) {
                    Object start = params.get(fieldName + "_Start");
                    Object end = params.get(fieldName + "_End");
                    if (StringUtil.isEmpty(start) && StringUtil.isEmpty(end)) {
                        continue;
                    }
                    boolean isDateTime = StringUtil.equalsIgnoreCase(config.getString("avueType"), "datetime");
                    String format = formField.getString("format");
                    if (!StringUtil.isEmpty(start)) {
                        where.set(fieldName + "_Start", new Condition(fieldName, ">=", isDateTime ? DateUtil.parse((String)start, format) : start));
                    }
                    if (!StringUtil.isEmpty(end)) {
                        where.set(fieldName + "_End", new Condition(fieldName, "<=", isDateTime ? DateUtil.parse((String)end, format) : end));
                    }
                } else {
                    Object value = params.get(fieldName);
                    if (StringUtil.isEmpty(value)) {
                        continue;
                    }
                    String operation = FormDataUtil.getQueryType(componentType);
                    if (StringUtil.equalsIgnoreCase(operation, "equal")) {
                        where.set(fieldName, new Condition(fieldName, value));
                    } else if (StringUtil.equalsIgnoreCase(operation, "like")) {
                        where.set(fieldName, new Condition(fieldName, String.valueOf(value), Condition.LikeType.Contains));
                    }
                }
            }
        }
    }

    @Override
    public boolean createCustomFormTable(XjrFormScheme scheme, List<TableInfoDto> tableInfoDtoList) throws SQLException {
        String schemeStr = scheme.getScheme();
        JSONObject schemeJson = JSONObject.parseObject(schemeStr);
        String dbLinkId = schemeJson.getString(FormConstants.DB_LINK_ID);
        // 判断表是否存在
//        for (TableInfoDto tableInfoDto : tableInfoDtoList) {
//            String tableName = tableInfoDto.getName();
//            if (databaseLinkService.existTable(dbLinkId, tableName)){
//                throw new RuntimeException("表已存在：" + tableName);
//            }
//        }
        Connection connection = DataSourceUtil.getDataSource(dbLinkId).getConnection();
        JSONArray dbTables = schemeJson.getJSONArray(FormConstants.DB_TABLE);
        // 添加关联字段
        FormDataUtil.buildRelationField(dbTables, tableInfoDtoList);
        DbType dbType = JdbcUtils.getDbType(connection.getMetaData().getURL());
        List<String> sqlList = new ArrayList<>();
        tableInfoDtoList.stream().map(tableInfoDto -> {
            Integer opr = tableInfoDto.getOpr();
            TableInfo tableInfo = BeanUtil.copy(tableInfoDto, TableInfo.class);
            tableInfo.setFields(BeanUtil.copyList(tableInfoDto.getFields(), TableField.class));
            // 添加公共字段
            TableInfoUtil.addComFieldAndKey(tableInfo);
            // 生成建表sql
            if (opr == null || opr != 1) {
                if (opr != null && opr == 3) {
                    // 删除旧表
                    sqlList.add(SqlUtil.buildDeleteTableSql(tableInfo.getName()));
                }
                // 生成建表语句
                sqlList.addAll(SqlUtil.buildCreateTableSql(dbType, tableInfo));
            }
            return tableInfo;
        }).collect(Collectors.toList());
        try {
            dbExecutor.batchExecuteNonParam(dbLinkId, sqlList.toArray(new String[]{}));
        } catch (SQLException e) {
            log.error("执行sql失败： " + sqlList, e);
            throw e;
        }
        return true;
    }

    @Override
    public List<SystemFormVo> getSystemFormList(String keyword, Integer type) {
        if (!StringUtil.isEmpty(keyword)) {
            keyword = StringPool.PERCENT + keyword + StringPool.PERCENT;
        }
        return this.baseMapper.getSystemFormList(keyword, type);
    }

    @Override
    public SystemFormVo getSystemFormByFormId(String formId) {
        return this.baseMapper.getSystemFormByFormId(formId);
    }

    public String getFullUrlOfSystemForm(String formId) {
        SystemFormVo systemForm = this.baseMapper.getSystemFormByFormId(formId);
        return systemForm.getUrl();
    }

    @Override
    public JSONArray getBindfields(String id, Integer type) throws Exception {
        XjrFormScheme xjrFormScheme = null;
        if (type == 1) {
            xjrFormScheme = schemeService.getById(id);
        } else if (type == 0) {
            xjrFormScheme = this.getSchemeByFormId(id);
        }
        JSONArray result = new JSONArray();
        if (xjrFormScheme != null) {
            String scheme = xjrFormScheme.getScheme();
            JSONObject schemeObj = JSONObject.parseObject(scheme);
            String dbLinkId = schemeObj.getString(FormConstants.DB_LINK_ID);
            JSONArray dbTables = schemeObj.getJSONArray(FormConstants.DB_TABLE);
            String mainTableName = "";
            for (int i = 0; i < dbTables.size(); i++) {
                JSONObject dbTable = dbTables.getJSONObject(i);
                if (StringUtil.isBlank(dbTable.getString(FormConstants.DB_TABLE_RELATION_NAME))) {
                    mainTableName = dbTable.getString(FormConstants.DB_TABLE_NAME);
                    break;
                }
            }
            List<TableColumnInfo> tableColumnInfos = xjrBaseDatabaseLinkService.getFieldByIdAndTableName(dbLinkId, mainTableName);
            for (TableColumnInfo tableColumnInfo : tableColumnInfos) {
                result.add(tableColumnInfo.getName());
            }
        }
        return result;
    }

    @Override
    public FormSchemeInfoVo getFormByModuleId(String moduleId) {
        XjrFormSchemeInfo xjrFormSchemeInfo = this.getOne(Wrappers.<XjrFormSchemeInfo>query().lambda().eq(XjrFormSchemeInfo::getSchemeId, moduleId).eq(XjrFormSchemeInfo::getType,2));
        FormSchemeInfoVo formSchemeInfoVo = new FormSchemeInfoVo();
        XjrBaseModule xjrBaseModule = moduleService.getById(moduleId);
        if(xjrFormSchemeInfo==null){
            XjrFormRelation formRelation = formRelationService.getOne(Wrappers.<XjrFormRelation>query().lambda().eq(XjrFormRelation::getModuleId, moduleId));
            if(formRelation!=null){
                String formId = formRelation.getFormId();
                xjrFormSchemeInfo=this.getById(formId);
            }
        }
        if(xjrFormSchemeInfo!=null) {
            formSchemeInfoVo = BeanUtil.copy(xjrFormSchemeInfo, FormSchemeInfoVo.class);
        }
        if(xjrBaseModule!=null){
            formSchemeInfoVo.setUrlAddress(xjrBaseModule.getUrlAddress());
        }
        return formSchemeInfoVo;
    }
}
